#pragma once

#ifndef _H_ZQDBASE_H_
#define _H_ZQDBASE_H_

#include <mdbase.h>

#if defined(LIB_ZQDB_API) && defined(WIN32)
#ifdef LIB_ZQDB_API_EXPORT
#define ZQDB_API_EXPORT __declspec(dllexport)
#else
#define ZQDB_API_EXPORT __declspec(dllimport)
#endif
#else
#define ZQDB_API_EXPORT 
#endif

#if defined(__cplusplus)
extern "C" {
#endif//

#pragma pack(push, 1)

#define ZQDB_STATUS_OK 0
#define ZQDB_STATUS_ERROR 1
#define ZQDB_STATUS_EACCES 2 //Permission denied
#define ZQDB_STATUS_DB_NOT_OPEN 3
#define ZQDB_STATUS_TABLE_NOT_OPEN 4
#define ZQDB_STATUS_INVALID_PARAM 5
#define ZQDB_STATUS_BAD_ALLOC 6
#define ZQDB_STATUS_EXCEPTION 7
#define ZQDB_STATUS_NOT_EXIST 8
#define ZQDB_STATUS_MEM_OVERFLOW 9
#define ZQDB_STATUS_IN_USE 10
#define ZQDB_STATUS_TIMEOUT 11
#define ZQDB_STATUS_DISCONNECT 12
#define ZQDB_STATUS_INIT 13
#define ZQDB_STATUS_VERSION 14

#define ZQDB_LOG_LEVEL_NONE	0
#define ZQDB_LOG_LEVEL_ERROR 1
#define ZQDB_LOG_LEVEL_WARN	2
#define ZQDB_LOG_LEVEL_INFO	3
#define ZQDB_LOG_LEVEL_DEBUG 4
//特殊消息根据前缀判断json/xml，如：json是{xxx}，xml是<xxx>

#define ZQDBLogSet MDBLogSet
/*	typedef void(*ZQDB_LOG_CB)(int level, char const* const format, void const* const args);
	ZQDB_API_EXPORT void ZQDBLogSet(ZQDB_LOG_CB cb);
	ZQDB_API_EXPORT void ZQDBLogF(int level, char const* const format, ...);
	ZQDB_API_EXPORT int ZQDBLogPrintF(char const* const format, void const* const args);
	ZQDB_API_EXPORT int ZQDBSLogF(char* const buf, size_t const buflen, char const* const format, void const* const args);

#define LOG4C(level,format,...) ZQDBLogF(level, format, ##__VA_ARGS__)
#define LOG4E(format,...) LOG4C(1, "[%s:%d] " format, __FILE__, __LINE__, ##__VA_ARGS__)
#define LOG4W(format,...) LOG4C(2, format, ##__VA_ARGS__)
#define LOG4I(format,...) LOG4C(3, format, ##__VA_ARGS__)
#define LOG4D(format,...) LOG4C(4, "[%s] " format, __FUNCTION__, ##__VA_ARGS__)*/

	///

#define ZQDB_INVALID_VALUE (1e16)
#define ZQDB_INVALID_CTL_VALUE (1e15)
#define ZQDB_ZERO_CTL_VALUE (1e-10)
#define ZQDB_4_5_CTL_VALUE_ (0.500001)
#define ZQDBIsZeroValue(v) ((v)>-ZQDB_ZERO_CTL_VALUE && (v)<ZQDB_ZERO_CTL_VALUE)
#define ZQDBIsInvalidValue(v) ((v)<-ZQDB_INVALID_CTL_VALUE || (v)>ZQDB_INVALID_CTL_VALUE)
#define ZQDBIsEqualValue(x,y) ((x)>(y)-ZQDB_ZERO_CTL_VALUE && (x)<((y)+ZQDB_ZERO_CTL_VALUE))

#define ZQDB_INVALID_POS (size_t)-1
#define ZQDBIsInvalidPos(p) ((p)==ZQDB_INVALID_POS)

#define		MAX_EXCHANGE_LENGTH		7	//市场代码最大长度
#define		MAX_PRODUCT_LENGTH		7	//产品代码最大长度
#define		MAX_CODE_LENGTH			31	//代码最大长度
#define		MAX_NAME_LENGTH			63	//名称最大长度
#define		MAX_ORDER_LENGTH		101	//订单ID最大长度
#define		MAX_CONTENT_LENGTH		3000 //内容最大长度

	///

	typedef enum ZQDB_MSG_TYPE
	{
		ZQDB_MSG_UNKNOWN = 0,
		ZQDB_MSG_NOTIFY,
		ZQDB_MSG_REQUEST_DO,
		ZQDB_MSG_REQUEST_QUERY,
		ZQDB_MSG_RESPONSE,
	}ZQDB_MSG_TYPE;
	typedef struct ZQDB_MSG
	{
		ZQDB_MSG_TYPE msg;
	}ZQDB_MSG;
	typedef struct ZQDB_MSG *HNMSG;
#define ZQDB_MSG_CB_HANDLED 0X00000001
	typedef int(*ZQDB_MSG_CB)(HNMSG h, size_t* flags); //消息回调

	///

	typedef enum ZQDB_HANDLE_TYPE
	{
		ZQDB_HANDLE_TYPE_UNKNOWN = 0,
		ZQDB_HANDLE_TYPE_CLIENT,
		ZQDB_HANDLE_TYPE_HTTP_CLIENT,
		ZQDB_HANDLE_TYPE_HTTPS_CLIENT,
		ZQDB_HANDLE_TYPE_SERVER,
		ZQDB_HANDLE_TYPE_SESSION,
		ZQDB_HANDLE_TYPE_HTTP_SESSION,
		ZQDB_HANDLE_TYPE_TABLE,
		ZQDB_HANDLE_TYPE_TABLE_DATA,
		ZQDB_HANDLE_TYPE_STATUS,
		ZQDB_HANDLE_TYPE_EXCHANGE,
		ZQDB_HANDLE_TYPE_PRODUCT,
		ZQDB_HANDLE_TYPE_CODE,
		ZQDB_HANDLE_TYPE_DATA,
		ZQDB_HANDLE_TYPE_CATEGORY,
		ZQDB_HANDLE_TYPE_MODULE,
		ZQDB_HANDLE_TYPE_USER,
		ZQDB_HANDLE_TYPE_CALCINPUT,
		ZQDB_HANDLE_TYPE_CALCFUNC,
		ZQDB_HANDLE_TYPE_CALCDATA,
		ZQDB_HANDLE_TYPE_CALCULATOR,
		ZQDB_HANDLE_TYPE_CALCMODULE,
	}ZQDB_HANDLE_TYPE;

	typedef struct ZQDB_HANDLE
	{
		ZQDB_HANDLE_TYPE type;
	}ZQDB_HANDLE;

	typedef struct ZQDB_HANDLE *HZQDB;

	////

//通用状态
#define ZQDB_STATUS_OFFLINE '0' //离线
#define ZQDB_STATUS_CONNECT '1' //连接中
#define ZQDB_STATUS_CONNECTED '2' //已连接
#define ZQDB_STATUS_LOGGED '3' //已登录

//证券主要状态：
//连接状态，Cli和Srv连接状态
//行情状态，包括市场、产品、代码状态，其中市场包括连接状态和市场状态
//交易状态，即用户状态，也就是说用户的连接状态
//其中连接状态提供专门一张表用于表示各种状态，名称分别是服务（zqsrv）、市场（CFFEX）、用户（USER）
#define STR_ZQDB_TABLE_STATUS "STATUS"

//模块
//所有模块表 MODULE = 模块列表[NAME,...]
#define STR_ZQDB_TABLE_MODULE "MODULE"

	typedef struct tagZQDBStatusInfo
	{
		char Name[MAX_NAME_LENGTH + 1]; //状态名称，分别是市场（CFFEX）、服务（zqsrv）、模块名（ctp）
		char Status; //STATUS_OFFLINE
	}ZQDBSTATUSINFO, *PZQDBSTATUSINFO;
	DECLARE_MDB_FIELD(ZQDB_API_EXPORT, ZQDB, STATUS, NAME);
	DECLARE_MDB_FIELD(ZQDB_API_EXPORT, ZQDB, STATUS, STATUS);
	DECLARE_MDB_FIELD_TABLE(ZQDB_API_EXPORT, ZQDB, STATUS, 2);
	DECLARE_MDB_FIELD_NAME_TABLE(ZQDB_API_EXPORT, ZQDB, STATUS);

#define ZQDB_MODULE_FLAG_MARKET 0x01 //行情模块
#define ZQDB_MODULE_FLAG_TRADE 0x02 //交易模块
//
#define ZQDB_MODULE_FLAG_EXCHANGE_QH 0x10 //国内期货市场
#define ZQDB_MODULE_FLAG_EXCHANGE_HSJ 0x20 //沪深京市场
	typedef struct tagZQDBModuleInfo
	{
		char Code[MAX_CODE_LENGTH + 1]; //模块标识（ctp）
		char Name[MAX_NAME_LENGTH + 1]; //模块名称，模块名（ctp）
		//char Desc[MAX_CONTENT_LENGTH + 1]; //模块描述
		uint32_t flags; //模块标志
	}ZQDBMODULEINFO,*PZQDBMODULEINFO;
	DECLARE_MDB_FIELD(ZQDB_API_EXPORT, ZQDB, MODULE, CODE);
	DECLARE_MDB_FIELD(ZQDB_API_EXPORT, ZQDB, MODULE, NAME);
	DECLARE_MDB_FIELD(ZQDB_API_EXPORT, ZQDB, MODULE, FLAGS);
	DECLARE_MDB_FIELD_TABLE(ZQDB_API_EXPORT, ZQDB, MODULE, 3);
	DECLARE_MDB_FIELD_NAME_TABLE(ZQDB_API_EXPORT, ZQDB, MODULE);

	//终端类型
	enum ZQDB_APP_TYPE
	{
		ZQDB_APP_STANDALONE = 0, //单机
		ZQDB_APP_SERVER, //服务器
		ZQDB_APP_CLIENT, //客户端
	};

	//运行模式
	enum ZQDB_APP_RUN_MODE
	{
		ZQDB_APP_RUN_REAL = 0, //实盘
		ZQDB_APP_RUN_MOCK, //模拟
		ZQDB_APP_RUN_TEST, //测试
	};

	//API

	ZQDB_API_EXPORT void ZQDBToHex(char *src, int src_len, char *out);
	ZQDB_API_EXPORT void ZQDBFromHex(char *src, int src_len, char *out);

	ZQDB_API_EXPORT int ZQDBEn64(const char *str, int str_len, char *encode, int encode_len, int new_line);
	ZQDB_API_EXPORT int ZQDBDe64(const char *str, int str_len, char *decode, int decode_len, int new_line);

#define ZQDB_MD5_DIGEST_LENGTH 16
	ZQDB_API_EXPORT int ZQDBMD5(const char *src, int src_len, char* out);

# define ZQDB_SHA_DIGEST_LENGTH 20
	ZQDB_API_EXPORT int ZQDBSHA1(const char *src, int src_len, char* out);

	//# define ZQDB_SHA224_DIGEST_LENGTH    28
	//# define ZQDB_SHA256_DIGEST_LENGTH    32
	//# define ZQDB_SHA384_DIGEST_LENGTH    48
# define ZQDB_SHA512_DIGEST_LENGTH    64
	ZQDB_API_EXPORT int ZQDBSHA512(const char *src, int src_len, char* out);

	ZQDB_API_EXPORT const char* ZQDBGetVersion();

	ZQDB_API_EXPORT size_t ZQDBGetAppID();
	ZQDB_API_EXPORT const char* ZQDBGetAppName();
	ZQDB_API_EXPORT const char* ZQDBGetAppKey();
	ZQDB_API_EXPORT const char* ZQDBGetAppVersion();

	ZQDB_API_EXPORT ZQDB_APP_TYPE ZQDBGetAppType();
#define ZQDBIsStandAlone() (ZQDBGetAppType() == ZQDB_APP_STANDALONE)
#define ZQDBIsServer() (ZQDBGetAppType() == ZQDB_APP_SERVER)
#define ZQDBIsClient() (ZQDBGetAppType() == ZQDB_APP_CLIENT)
	ZQDB_API_EXPORT ZQDB_APP_RUN_MODE ZQDBGetAppRunMode();
#define ZQDBIsTest() (ZQDBGetAppRunMode() == ZQDB_APP_RUN_TEST)

	ZQDB_API_EXPORT const char* ZQDBGetDataDir();

	ZQDB_API_EXPORT bool ZQDBIsUserOk();
	ZQDB_API_EXPORT const char* ZQDBGetUserID();
	ZQDB_API_EXPORT const char* ZQDBGetUserRole();
	ZQDB_API_EXPORT bool  ZQDBIsUserAdmin();
	ZQDB_API_EXPORT bool  ZQDBIsUserObserver();
	ZQDB_API_EXPORT size_t ZQDBGetUserPoints();
	ZQDB_API_EXPORT bool  ZQDBIsUserReal();
	ZQDB_API_EXPORT size_t ZQDBGetUserMaxSubs();
	ZQDB_API_EXPORT size_t ZQDBGetUserMaxStrategys();


	//ZQDB_API_EXPORT const char* ZQDBPay(char* str, size_t len);

	//ZQDB_API_EXPORT bool ZQDBIsInvalidValue(double value);
	//ZQDB_API_EXPORT bool ZQDBIsInvalidPos(size_t pos);
#ifdef _DEBUG
	ZQDB_API_EXPORT void ZQDBAddInvalidPtr(void* ptr);
	ZQDB_API_EXPORT void ZQDBRemoveInvalidPtr(void* ptr);
	ZQDB_API_EXPORT bool ZQDBIsInvalidPtr(void* ptr);
#endif//

	ZQDB_API_EXPORT int ZQDBGetTableFiledCount(HZQDB module, const char* table);
	ZQDB_API_EXPORT int ZQDBGetTableFiledIndex(HZQDB module, const char* table, const char* name);
	ZQDB_API_EXPORT const char* ZQDBGetTableFiledName(HZQDB module, const char* table, size_t index);

	ZQDB_API_EXPORT ssize_t ZQDBGetAttrAsInt(const char* key, ssize_t def);
	ZQDB_API_EXPORT double ZQDBGetAttrAsDouble(const char* key, double def);
	ZQDB_API_EXPORT char* ZQDBGetAttrAsStr(const char* key, char* str, int len);
	//ZQDB_API_EXPORT size_t GetAttrCount(const std::string& key);
	//ZQDB_API_EXPORT bool GetAttr(const std::string& key, size_t pos, std::string& value);

	//ZQDB_API_EXPORT HZQDB ZQDBCloseTable(HZQDB h);
#define ZQDB_OPEN_TABLE_FLAG_SYNC_DATA 0x80000000 //同步TableData标志
	ZQDB_API_EXPORT HZQDB ZQDBOpenTable(const char* name, uint32_t flags);
	ZQDB_API_EXPORT HZQDB ZQDBOpenOrInitTable(const char* name, MDB_FIELD* field, size_t field_num, size_t max_count, uint32_t flags);
	ZQDB_API_EXPORT HZQDB ZQDBOpenTableEx(HZQDB h, const char* name, uint32_t flags);
	ZQDB_API_EXPORT HZQDB ZQDBOpenOrInitTableEx(HZQDB h, const char* name, MDB_FIELD* field, size_t field_num, size_t max_count, uint32_t flags);

	ZQDB_API_EXPORT HMDB ZQDBGetMDb(HZQDB h);
	ZQDB_API_EXPORT HMTABLE ZQDBGetMTable(HZQDB h, HMDB* hdb);

	//ZQDB_API_EXPORT const char* ZQDBGetTableName(HZQDB h);
	ZQDB_API_EXPORT HZQDB ZQDBFindTable(const char* name);
	ZQDB_API_EXPORT HZQDB ZQDBFindTableEx(HZQDB h, const char* name);

	ZQDB_API_EXPORT bool ZQDBIsDataOfTable(HZQDB h, const char* name);

	ZQDB_API_EXPORT size_t ZQDBGetTableDataMaxCount(HZQDB h);
	ZQDB_API_EXPORT size_t ZQDBGetTableDataCount(HZQDB h);
	ZQDB_API_EXPORT void ZQDBClearTableData(HZQDB h);
	ZQDB_API_EXPORT size_t ZQDBGetTableData(HZQDB h, size_t pos, HZQDB* data, size_t count);
	ZQDB_API_EXPORT HZQDB ZQDBGetTableDataByPos(HZQDB h, size_t pos);
	typedef bool(*ZQDB_FIND_TABLE_DATA_CB)(HZQDB h, void* data);
	ZQDB_API_EXPORT size_t ZQDBFindTableData(HZQDB h, HZQDB* data, size_t count, void* user_data, ZQDB_FIND_TABLE_DATA_CB cb);
	ZQDB_API_EXPORT HZQDB ZQDBFindTableDataEx(HZQDB h, void* user_data, ZQDB_FIND_TABLE_DATA_CB cb);
	ZQDB_API_EXPORT HZQDB ZQDBAddAndGetTableData(HZQDB h, void* data);
	//ZQDB_API_EXPORT void ZQDBAddTableData(HZQDB h, void* data);
	//ZQDB_API_EXPORT MDB_STATUS ZQDBUpdateTableData(HZQDB hdata, void* data);
	//ZQDB_API_EXPORT MDB_STATUS ZQDBUpdateCustomFieldData(HZQDB hdata, MDB_FIELD* field, size_t field_num, void* data);
	ZQDB_API_EXPORT MDB_STATUS ZQDBRemoveTableDataValue(HZQDB h, size_t pos, size_t count);
	ZQDB_API_EXPORT size_t ZQDBGetTableDataValue(HZQDB h, size_t pos, void** data, size_t count);
	ZQDB_API_EXPORT size_t ZQDBCopyTableDataValue(HZQDB h, size_t pos, void* data, size_t count);
	ZQDB_API_EXPORT MDB_STATUS ZQDBAddTableDataValue(HZQDB h, void* data);
	ZQDB_API_EXPORT MDB_STATUS ZQDBUpdateTableDataValue(HZQDB hdata, void* data);
	ZQDB_API_EXPORT MDB_STATUS ZQDBUpdateTableDataFieldValue(HZQDB hdata, MDB_FIELD* field, size_t field_num, void* data);

#define ZQDB_FLAG_NONE			0
#define ZQDB_FLAG_DISABLE		0x00000001
#define ZQDB_FLAG_MASK			0X000000FF
#define ZQDB_USER_FLAG_MASK		0XFFFFFF00

//CODE Flag
#define ZQDB_CODE_FLAG_SUBSCRIBE	0x00000100
#define ZQDB_CODE_FLAG_SELFSEL		0x00000200
#define ZQDB_CODE_FLAG_MASK			0X0000FF00
#define ZQDB_CODE_USER_FLAG_MASK	0XFFFF0000

	ZQDB_API_EXPORT void ZQDBSetFlags(HZQDB h, uint32_t flags);
	ZQDB_API_EXPORT void ZQDBAddFlags(HZQDB h, uint32_t flags);
	ZQDB_API_EXPORT void ZQDBRemoveFlags(HZQDB h, uint32_t flags);
	ZQDB_API_EXPORT size_t ZQDBModifyFlags(HZQDB h, size_t add, size_t remove);
	ZQDB_API_EXPORT size_t ZQDBGetFlags(HZQDB h);
	ZQDB_API_EXPORT size_t ZQDBHasFlags(HZQDB h, uint32_t flags);

	ZQDB_API_EXPORT bool ZQDBEnable(HZQDB h);
	ZQDB_API_EXPORT bool ZQDBDisable(HZQDB h);
	ZQDB_API_EXPORT bool ZQDBIsDisable(HZQDB h);
	ZQDB_API_EXPORT bool ZQDBIsAnyDisabledModule();

	ZQDB_API_EXPORT HZQDB ZQDBGetModule(HZQDB h);
	ZQDB_API_EXPORT HZQDB ZQDBGetParentTable(HZQDB h);
	ZQDB_API_EXPORT HZQDB ZQDBGetParent(HZQDB h);
	ZQDB_API_EXPORT HZQDB ZQDBGetTable(HZQDB h);
	ZQDB_API_EXPORT void* ZQDBGetValue(HZQDB h);

	//是否src是dst的子孙
	ZQDB_API_EXPORT bool ZQDBIsAncestor(HZQDB src, HZQDB dst);
	//是否src是dst的祖先
	ZQDB_API_EXPORT bool ZQDBIsDescendant(HZQDB src, HZQDB dst);

	ZQDB_API_EXPORT MDB_STATUS ZQDBNormalizeField(HZQDB h, MDB_FIELD* field, size_t field_num);
	ZQDB_API_EXPORT MDB_STATUS ZQDBGetFieldValue(HZQDB h, MDB_FIELD* field, size_t field_num, char* data);
	ZQDB_API_EXPORT MDB_STATUS ZQDBGetFieldAsInt(HZQDB h, MDB_FIELD* field, size_t field_num, ssize_t* value);
	ZQDB_API_EXPORT MDB_STATUS ZQDBGetFieldAsDouble(HZQDB h, MDB_FIELD* field, size_t field_num, double* value);
	ZQDB_API_EXPORT MDB_STATUS ZQDBGetFieldAsStr(HZQDB h, MDB_FIELD* field, size_t field_num, char** data, size_t* size, const char* format);

	//ZQDB_API_EXPORT size_t ZQDBGetAllStatusCount();
	//ZQDB_API_EXPORT size_t ZQDBGetAllStatus(STATUSINFO* status, size_t count);
	ZQDB_API_EXPORT HZQDB ZQDBSetStatus(const char* name, char status);
	ZQDB_API_EXPORT HZQDB ZQDBGetStatus(const char* name);

	ZQDB_API_EXPORT size_t ZQDBGetModuleCount();
	ZQDB_API_EXPORT HZQDB ZQDBGetModuleAt(size_t pos);

	typedef void(*ZQDB_ASYNC_CB)(void* data); //回调
#define ZQDB_POST_TID_BEST ((size_t)-1)
#define ZQDB_POST_TID_ANY ((size_t)-2)
	ZQDB_API_EXPORT void ZQDBPost(ZQDB_ASYNC_CB cb, void* data, size_t tid);
	//ZQDB_API_EXPORT size_t ZQDBPostTime(struct tm time, ZQDB_ASYNC_CB cb, void* data, size_t tid);
	//ZQDB_API_EXPORT size_t ZQDBPostDelay(size_t millis, ZQDB_ASYNC_CB cb, void* data, size_t tid);
	//ZQDB_API_EXPORT size_t ZQDBCancel(size_t id, size_t tid);

	ZQDB_API_EXPORT bool ZQDBIsIPC();
	ZQDB_API_EXPORT bool ZQDBIsRPC();

	ZQDB_API_EXPORT HZQDB ZQDBClient();
	ZQDB_API_EXPORT bool ZQDBIsConnect();
	ZQDB_API_EXPORT bool ZQDBReConnect();
	ZQDB_API_EXPORT bool ZQDBIsLogin(ZQDB_MSG** msg);
	ZQDB_API_EXPORT bool ZQDBIsLoginSuccess();

	//相对datadir路径
	ZQDB_API_EXPORT bool ZQDBRegisterHttpGetFile(const char* file);
	ZQDB_API_EXPORT bool ZQDBRequestHttpGetFile(const char* file);
	ZQDB_API_EXPORT bool ZQDBRequestHttpGetToFile(const char* file, const char* host, const char* port, const char* target, const char* head[][2], size_t head_count);
	ZQDB_API_EXPORT bool ZQDBRequestHttpPostToFile(const char* file, const char* host, const char* port, const char* target, const char* head[][2], size_t head_count, const char* body);

	ZQDB_API_EXPORT HZQDB ZQDBServer();
	ZQDB_API_EXPORT bool ZQDBIsListen();
	ZQDB_API_EXPORT bool ZQDBStartListen();
	ZQDB_API_EXPORT void ZQDBStopListen();
	ZQDB_API_EXPORT void ZQDBPauseServer(bool ipc, bool rpc);
	ZQDB_API_EXPORT void ZQDBRestartServer(bool ipc, bool rpc);
	ZQDB_API_EXPORT bool ZQDBIsIPCServer();
	ZQDB_API_EXPORT bool ZQDBIsRPCServer();
	ZQDB_API_EXPORT size_t ZQDBGetIPCCount();
	ZQDB_API_EXPORT size_t ZQDBGetRPCCount();

	ZQDB_API_EXPORT void ZQDBSubscribeAll(HZQDB peer);
	ZQDB_API_EXPORT void ZQDBAddSubscribe(HZQDB peer, HZQDB* hs, size_t hcount);
	ZQDB_API_EXPORT void ZQDBRemoveSubscribe(HZQDB peer, HZQDB* hs, size_t hcount);

	ZQDB_API_EXPORT bool ZQDBIPCIsAnySubscribe(HZQDB* hs, size_t hcount);
	ZQDB_API_EXPORT bool ZQDBRPCIsAnySubscribe(HZQDB* hs, size_t hcount);

	ZQDB_API_EXPORT bool ZQDBPeerIsIPC(HZQDB peer);
	ZQDB_API_EXPORT bool ZQDBPeerIsRPC(HZQDB peer);
	ZQDB_API_EXPORT bool ZQDBPeerIsSubscribeAll(HZQDB peer);
	ZQDB_API_EXPORT bool ZQDBPeerIsAnySubscribe(HZQDB peer, HZQDB* hs, size_t hcount);

	ZQDB_API_EXPORT uint32_t ZQDBReqID();

#define STR_ZQDB_MSG_PARAM_ERROR_CODE "errcode"
#define ZQDB_MSG_PARAM_ERROR_CODE_NOERROR 0

#define STR_ZQDB_MSG_PARAM_ERROR_MESSAGE "errmsg"

	ZQDB_API_EXPORT ZQDB_MSG* ZQDBMsgNew(ZQDB_MSG_TYPE msg);
	ZQDB_API_EXPORT ZQDB_MSG* ZQDBMsgParse(const char* data, int size);
	ZQDB_API_EXPORT int ZQDBMsgRef(ZQDB_MSG* msg);
	ZQDB_API_EXPORT int ZQDBMsgDelete(ZQDB_MSG* msg);
	ZQDB_API_EXPORT const char* ZQDBMsgSerialize(ZQDB_MSG* msg, size_t* size);
	typedef enum ZQDB_MSG_CLEAR_FLAGS
	{
		//ZQDB_MSG_CLEAR_ALL = 0,
		ZQDB_MSG_CLEAR_PARAM = 0X01,
		//ZQDB_MSG_CLEAR_ATTR = 0X02,
		ZQDB_MSG_CLEAR_DATA = 0X04,
	}ZQDB_MSG_CLEAR_FLAGS;
	ZQDB_API_EXPORT int ZQDBMsgClear(ZQDB_MSG* msg, size_t flags);
	ZQDB_API_EXPORT int ZQDBMsgSetNode(ZQDB_MSG* msg, HZQDB h);
	ZQDB_API_EXPORT HZQDB ZQDBMsgGetNode(ZQDB_MSG* msg);
	ZQDB_API_EXPORT void ZQDBMsgSetType(ZQDB_MSG* msg, uint32_t type);
	ZQDB_API_EXPORT uint32_t ZQDBMsgGetType(ZQDB_MSG* msg);
	ZQDB_API_EXPORT int ZQDBMsgSetID(ZQDB_MSG* msg, uint32_t id);
	ZQDB_API_EXPORT uint32_t ZQDBMsgGetID(ZQDB_MSG* msg);
	ZQDB_API_EXPORT int ZQDBMsgSetParam(ZQDB_MSG* msg, const char* name, const char* value);
	ZQDB_API_EXPORT int ZQDBMsgSetParamAsInt(ZQDB_MSG* msg, const char* name, ssize_t value);
	ZQDB_API_EXPORT int ZQDBMsgSetParamAsUInt(ZQDB_MSG* msg, const char* name, size_t value);
	ZQDB_API_EXPORT int ZQDBMsgSetParamAsDouble(ZQDB_MSG* msg, const char* name, double value);
	ZQDB_API_EXPORT const char* ZQDBMsgGetParam(ZQDB_MSG* msg, const char* name);
	ZQDB_API_EXPORT ssize_t ZQDBMsgGetParamAsInt(ZQDB_MSG* msg, const char* name, ssize_t def);
	ZQDB_API_EXPORT size_t ZQDBMsgGetParamAsUInt(ZQDB_MSG* msg, const char* name, size_t def);
	ZQDB_API_EXPORT double ZQDBMsgGetParamAsDouble(ZQDB_MSG* msg, const char* name, double def);
	//ZQDB_API_EXPORT int ZQDBMsgSetAttr(ZQDB_MSG* msg, const char* data, const size_t size);
	//ZQDB_API_EXPORT const char* ZQDBMsgGetAttr(ZQDB_MSG* msg, size_t* size);
	ZQDB_API_EXPORT int ZQDBMsgSetData(ZQDB_MSG* msg, const char* data, const size_t size);
	ZQDB_API_EXPORT int ZQDBMsgAppendData(ZQDB_MSG* msg, const char* data, const size_t size);
	ZQDB_API_EXPORT const char* ZQDBMsgGetData(ZQDB_MSG* msg, size_t* size);
	
	//直接发送消息
	ZQDB_API_EXPORT int ZQDBSendMsg(ZQDB_MSG* msg);
	//ZQDB_API_EXPORT int ZQDBSendMsgToSrv(ZQDB_MSG* msg, ZQDB_MSG** rsp, size_t timeout);
	ZQDB_API_EXPORT int ZQDBRequest(ZQDB_MSG* msg, ZQDB_MSG** rsp, size_t timeout);
	ZQDB_API_EXPORT int ZQDBRequestEx(HZQDB h, ZQDB_MSG* msg, ZQDB_MSG** rsp, size_t timeout);
	typedef void(*ZQDB_REQUEST_CB)(ZQDB_MSG* req, ZQDB_MSG* rsp, void* user_data);
	ZQDB_API_EXPORT int ZQDBRequestCB(ZQDB_MSG* msg, ZQDB_REQUEST_CB cb, void* user_data);
	ZQDB_API_EXPORT int ZQDBRequestCBEx(HZQDB h, ZQDB_MSG* msg, ZQDB_REQUEST_CB cb, void* user_data);
	ZQDB_API_EXPORT void ZQDBCancelRequest(ZQDB_MSG* msg);
	ZQDB_API_EXPORT uint32_t ZQDBStoreRequest(ZQDB_MSG* msg);
	ZQDB_API_EXPORT ZQDB_MSG* ZQDBFindRequest(uint32_t reqid);
	ZQDB_API_EXPORT void ZQDBRemoveRequest(uint32_t reqid);

	//ZQDB_API_EXPORT void ZQDBBroadcastIPCMsg(ZQDB_MSG* msg);
	//ZQDB_API_EXPORT void ZQDBBroadcastRPCMsg(ZQDB_MSG* msg);
	typedef bool(*ZQDB_BROADCAST_CB)(HZQDB h, void* user_data);
	ZQDB_API_EXPORT bool ZQDBBroadcastIPC(ZQDB_BROADCAST_CB fn, void* user_data);
	ZQDB_API_EXPORT bool ZQDBBroadcastRPC(ZQDB_BROADCAST_CB fn, void* user_data);
	
	enum ZQDB_NOTIFY_TYPE {
		ZQDB_NOTIFY_NONE = 0,
		ZQDB_NOTIFY_STATUS,
		ZQDB_NOTIFY_ADD,
		ZQDB_NOTIFY_REMOVE,
		ZQDB_NOTIFY_UPDATE,
	};

	typedef void(*ZQDB_NOTIFY_CB)(HZQDB h, ZQDB_NOTIFY_TYPE notify);

	ZQDB_API_EXPORT void ZQDBNotify(HZQDB h, ZQDB_NOTIFY_TYPE notify);
	//ZQDB_API_EXPORT void ZQDBNotifyDispatch(HMDB hdb, HMTABLE htb, MDB_NOTIFY_DATA* notify, ZQDB_NOTIFY_DISPATCH_CB cb, void* user_data);

#pragma pack(pop)

#if defined(__cplusplus)
}

//#include <limits>
#include <atomic>
#include <mutex>
#include <shared_mutex>
#include <condition_variable>
#include <thread>
#include <future>
#include <functional>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <chrono>

namespace zqdb {

	template<typename Ty>
	static inline bool IsZeroValue(Ty v) { return ZQDBIsZeroValue(v); }
	template<typename Ty>
	static inline bool IsInvalidValue(Ty v) { return ZQDBIsInvalidValue(v); }
	template<typename Ty>
	static inline bool IsEqualValue(Ty x, Ty y) { return ZQDBIsEqualValue(x, y); }

	static inline void Post(size_t tid, ZQDB_ASYNC_CB cb, void* data) { ZQDBPost(cb, data, tid); }
	static inline void Post(ZQDB_ASYNC_CB cb, void* data) { Post(ZQDB_POST_TID_BEST, cb, data); }
	/*static inline void PostTime(size_t tid, const struct tm& time, ZQDB_ASYNC_CB cb, void* data) { ZQDBPostTime(time, cb, data, tid); }
	static inline void PostTime(struct tm time, ZQDB_ASYNC_CB cb, void* data) { PostTime(ZQDB_POST_TID_BEST, time, cb, data); }
	static inline void PostDelay(size_t tid, size_t millis, ZQDB_ASYNC_CB cb, void* data) { ZQDBPostDelay(millis, cb, data, tid); }
	static inline void PostDelay(size_t millis, ZQDB_ASYNC_CB cb, void* data) { PostDelay(ZQDB_POST_TID_BEST, millis, cb, data); }
	static inline size_t Cancel(size_t tid, size_t id) { return ZQDBCancel(id, tid); }
	static inline size_t Cancel(size_t id) { return Cancel(ZQDB_POST_TID_BEST, id); }
	*/

	/*template<class F, class... Args>
	static inline auto Send(size_t tid, F&& f, Args&&... args)
		-> std::future<typename std::result_of<F(Args...)>::type>
	{
		using return_type = typename std::result_of<F(Args...)>::type;

		auto task = new std::packaged_task<return_type()>(
			std::bind(std::forward<F>(f), std::forward<Args>(args)...)
			);

		std::future<return_type> res = task->get_future();
		Post(tid, [](void* data) { auto task = (std::packaged_task<return_type()>*)data; (*task)(); delete task; }, task);
		return res;
	}
	template<class F, class... Args>
	static inline auto Send(F&& f, Args&&... args)
		-> std::future<typename std::result_of<F(Args...)>::type>
	{
		return Post(ZQDB_POST_TID_BEST, std::forward<F>(f), std::forward<Args>(args)...);
	}

	template<class _Ret>
	class TaskInfo
	{
	public:
		std::packaged_task<_Ret()>* task;
		size_t id = 0;
		TaskInfo(std::packaged_task<_Ret()>* task, size_t id) :task(task), id(id) {}
	};

	template<class F, class... Args>
	static inline auto SendTime(size_t tid, const struct tm& time, F&& f, Args&&... args)
		-> TaskInfo<typename std::result_of<F(Args...)>::type>
	{
		using return_type = typename std::result_of<F(Args...)>::type;

		auto task = new std::packaged_task<return_type()>(
			std::bind(std::forward<F>(f), std::forward<Args>(args)...)
			);

		size_t id = PostTime(tid, time, [](void* data) { auto task = (std::packaged_task<return_type()>*)data; (*task)(); delete task; }, task);
		return TaskInfo(task, id);
	}
	template<class F, class... Args>
	static inline auto SendTime(const struct tm& time, F&& f, Args&&... args)
		-> TaskInfo<typename std::result_of<F(Args...)>::type>
	{
		return PostTime(ZQDB_POST_TID_BEST, time, std::forward<F>(f), std::forward<Args>(args)...);
	}

	template<class F, class... Args>
	static inline auto SendDelay(size_t tid, const size_t delay, F&& f, Args&&... args)
		-> TaskInfo<typename std::result_of<F(Args...)>::type>
	{
		using return_type = typename std::result_of<F(Args...)>::type;

		auto task = new std::packaged_task<return_type()>(
			std::bind(std::forward<F>(f), std::forward<Args>(args)...)
			);

		size_t id = PostDelay(tid, delay, [](void* data) { auto task = (std::packaged_task<return_type()>*)data; (*task)(); delete task; }, task);
		return TaskInfo(task, id);
	}
	template<class F, class... Args>
	static inline auto SendDelay(const size_t delay, F&& f, Args&&... args)
		-> TaskInfo<typename std::result_of<F(Args...)>::type>
	{
		return PostDelay(ZQDB_POST_TID_BEST, delay, std::forward<F>(f), std::forward<Args>(args)...);
	}

	template<class _Ret>
	static inline bool Cancel(size_t tid, TaskInfo<_Ret>& info)
	{
		if (Cancel(tid, info.id)) {
			delete info.task;
			info.id = 0;
			return true;
		}
		return false;
	}
	template<class _Ret>
	static inline bool Cancel(TaskInfo<_Ret>& info)
	{
		return Cancel(ZQDB_POST_TID_BEST, info);
	}*/

	class Handle : public ZQDB_HANDLE
	{
	public:
		Handle(ZQDB_HANDLE_TYPE type) {
			this->type = type;
		}
	};

	class HandleEx : public Handle
	{
	public:
		size_t flags_ = 0;
	public:
		HandleEx(ZQDB_HANDLE_TYPE type, size_t flags = 0) :Handle(type), flags_(flags){

		}

		void SetFlags(size_t flags) { flags_ = flags; }
		void AddFlags(size_t flags) {
			flags_ |= flags;
		}
		void RemoveFlags(size_t flags) {
			flags_ &= ~flags;
		}
		size_t ModifyFlags(size_t add, size_t remove = 0) {
			flags_ |= add;
			flags_ &= ~remove;
			return flags_;
		}
		size_t GetFlags() const { return flags_; }
		size_t HasFlags(size_t flags) const {
			return flags_ & flags;
		}
	};

	template<class T>
	class HandleMap
	{
		typedef HandleMap<T> This;
	protected:
		HZQDB h_ = nullptr;

	public:
		void OnHandleChanged()
		{

		}

		void Clear()
		{
			h_ = nullptr;
		}
		bool IsOk() const { return h_ != nullptr; }
		HZQDB GetHandle() const
		{
			return h_;
		}
		void SetHandle(HZQDB h)
		{
			T* pT = static_cast<T*>(this);
			if (h_ != h) {
				h_ = h;
				pT->OnHandleChanged();
			}
		}
	};

	class Object {
	protected:
		HZQDB h_;
	public:
		Object(HZQDB h = nullptr) :h_(h) {}
		Object(const Object& o) = default;
		Object& operator=(const Object& o) = default;
		Object(Object&& o) = default;
		Object& operator=(Object&& o) = default;
		Object& operator=(HZQDB h) {
			h_ = h;
		}
		~Object() { }

		inline operator bool() const { return h_ != nullptr; }
		inline operator HZQDB() const { return h_; }

		inline HZQDB GetModule() const { return ZQDBGetModule(h_); }
		inline HZQDB GetParent() const { return ZQDBGetParent(h_); }
		inline void* GetValue() const { return ZQDBGetValue(h_); }

		inline MDB_STATUS NormalizeField(MDB_FIELD* field, size_t field_num) { return ZQDBNormalizeField(h_, field, field_num); }
		inline MDB_STATUS GetFieldValue(MDB_FIELD* field, size_t field_num, char* data) {
			if (MDB_STATUS_OK == NormalizeField(field, field_num)) {
				return ZQDBGetFieldValue(h_, field, field_num, data);
			}
			return MDB_STATUS_INVALID_PARAM;
		}
		inline MDB_STATUS GetFieldAsInt(MDB_FIELD* field, size_t field_num, ssize_t* value) {
			if (MDB_STATUS_OK == NormalizeField(field, field_num)) {
				return ZQDBGetFieldAsInt(h_, field, field_num, value);
			}
			return MDB_STATUS_INVALID_PARAM;
		}
		inline MDB_STATUS GetFieldAsDouble(MDB_FIELD* field, size_t field_num, double* value) {
			if (MDB_STATUS_OK == NormalizeField(field, field_num)) {
				return ZQDBGetFieldAsDouble(h_, field, field_num, value);
			}
			return MDB_STATUS_INVALID_PARAM;
		}
		inline MDB_STATUS GetFieldAsStr(MDB_FIELD* field, size_t field_num, char** data, size_t* size, const char* format = nullptr) {
			if (MDB_STATUS_OK == NormalizeField(field, field_num)) {
				return ZQDBGetFieldAsStr(h_, field, field_num, data, size, format);
			}
			return MDB_STATUS_INVALID_PARAM;
		}
		inline MDB_STATUS NormalizeField(MDB_FIELD& field) {
			return NormalizeField(&field, 1);
		}
		inline MDB_STATUS GetFieldValue(MDB_FIELD& field, char* data) {
			return GetFieldValue(&field, 1, data);
		}
		inline ssize_t GetFieldAsInt(MDB_FIELD& field, ssize_t def = 0) {
			ssize_t val = 0;
			if (MDB_STATUS_OK == GetFieldAsInt(&field, 1, &val)) {
				return val;
			}
			return def;
		}
		inline double GetFieldAsDouble(MDB_FIELD& field, double def = ZQDB_INVALID_VALUE) {
			double val = 0;
			if (MDB_STATUS_OK == GetFieldAsDouble(&field, 1, &val)) {
				return val;
			}
			return def;
		}
		inline const char* GetFieldAsStr(MDB_FIELD& field, char* str, size_t len, const char* fmt = nullptr) {
			if (MDB_STATUS_OK == GetFieldAsStr(&field, 1, &str, &len, fmt)) {
				return str;
			}
			return str;
		}
	};

	template<class TInfo, class TBase = Object>
	class ObjectT : public TBase {
		typedef TBase Base;
	public:
		using Base::Base;

		inline operator TInfo*() const
		{
			return (TInfo*)(this->GetValue());
		}

		inline TInfo *operator->() const
		{	// return pointer to resource
			return (TInfo*)(this->GetValue());
		}
	};

	template<class TInfo = tagZQDBStatusInfo>
	class StatusT : public ObjectT<TInfo> {
		typedef ObjectT<TInfo> Base;
	public:
		StatusT(HZQDB h = nullptr) :Base(h) {}
		StatusT(const char* name) :Base(ZQDBGetStatus(name)) {}
		~StatusT() { }

	};
	typedef StatusT<tagZQDBStatusInfo> Status;

	///

	class AllTableData : public std::vector<HZQDB> {
	protected:
		HZQDB htb_ = nullptr;
	public:
		AllTableData(const char* name, HZQDB h = nullptr) : AllTableData(ZQDBFindTableEx(h, name)) {}
		AllTableData(HZQDB htb) :htb_(htb) {
			std::vector<HZQDB>& vec = *this;
			vec.reserve(ZQDBGetTableDataMaxCount(htb));
			Update();
		}

		inline operator HZQDB() const { return htb_; }

		void Update()
		{
			std::vector<HZQDB>& vec = *this;
			size_t old_vec_count = vec.size();
			auto vec_count = ZQDBGetTableDataCount(htb_);
			if (old_vec_count < vec_count) {
				vec.resize(vec_count);
				vec.resize(old_vec_count + ZQDBGetTableData(htb_, old_vec_count, &vec[old_vec_count], vec_count - old_vec_count));
			}
		}
	};
	class AllTableDataFilter : public std::vector<HZQDB> {
	public:
		AllTableDataFilter(void* data, ZQDB_FIND_TABLE_DATA_CB cb, const char* name, HZQDB h = nullptr) : AllTableDataFilter(data, cb, ZQDBFindTableEx(h, name)) {}
		AllTableDataFilter(void* data, ZQDB_FIND_TABLE_DATA_CB cb, HZQDB htb) {
			std::vector<HZQDB>& vec = *this;
			auto vec_count = ZQDBGetTableDataCount(htb);
			if (vec_count) {
				vec.resize(vec_count);
				vec.resize(ZQDBFindTableData(htb, &vec[0], vec_count, data, cb));
			}
		}
	};
	/*template<const char const name[]>
	class AllObjectT : public AllTableData
	{
	public:
	AllObjectT() : AllTableData(name) {}
	AllObjectT(HZQDB module) : AllTableData(name, module) {}
	};*/
	template<class TInfo>
	class AllTableDataPtr : public std::vector<TInfo*> {
	protected:
		HZQDB htb_ = nullptr;
	public:
		AllTableDataPtr(const char* name, HZQDB h = nullptr) : AllTableDataPtr(ZQDBGetTableEx(h, name)) {}
		AllTableDataPtr(HZQDB htb) :htb_(htb) {
			std::vector<TInfo*>& vec = *this;
			vec.reserve(ZQDBGetTableDataMaxCount(htb));
			Update();
		}

		inline operator HZQDB() const { return htb_; }

		void Update()
		{
			std::vector<TInfo*>& vec = *this;
			size_t old_vec_count = vec.size();
			auto vec_count = ZQDBGetTableDataCount(htb_);
			if (old_vec_count < vec_count) {
				vec.resize(vec_count);
				vec.resize(ZQDBGetTableDataValue(htb_, old_vec_count, &vec[vec_count], vec_count - old_vec_count));
			}
		}
	};
	template<class TInfo>
	class AllTableDataValue : public std::vector<TInfo> {
	protected:
		HZQDB htb_ = nullptr;
	public:
		AllTableDataValue(const char* name, HZQDB h = nullptr) : AllTableDataValue(ZQDBGetTableEx(h, name)) {}
		AllTableDataValue(HZQDB htb) :htb_(htb) {
			std::vector<TInfo>& vec = *this;
			vec.reserve(ZQDBGetTableDataMaxCount(htb));
			Update();
		}

		inline operator HZQDB() const { return htb_; }

		void Update()
		{
			std::vector<TInfo>& vec = *this;
			size_t old_vec_count = vec.size();
			auto vec_count = ZQDBGetTableDataCount(htb_);
			if (old_vec_count < vec_count) {
				vec.resize(vec_count);
				vec.resize(ZQDBCopyTableDataValue(htb_, old_vec_count, &vec[vec_count], vec_count - old_vec_count));
			}
		}
	};

	class AllStatus : public AllTableData {
	public:
		AllStatus() :AllTableData(STR_ZQDB_TABLE_STATUS) {

		}
	};

	/*class AllModule {
	public:
		AllModule() {
			
		}

		size_t size() const
		{	// return length of sequence
			return ZQDBGetModuleCount();
		}

		HZQDB operator[](size_t pos) const
		{	// subscript nonmutable sequence
			return ZQDBGetModuleAt(pos);
		}

		HZQDB operator[](size_t pos)
		{	// subscript mutable sequence
			return ZQDBGetModuleAt(pos);
		}
	};*/

	///

	class Msg
	{
	private:
		ZQDB_MSG* msg_ = nullptr;
		bool delete_flag_ = false;
	public:
		Msg() {}
		enum FLAG {
			None,
			Ref,
			AutoDelete,
		};
		Msg(ZQDB_MSG* msg, FLAG flag = None) :msg_(msg) {
			if (flag == Ref) {
				ZQDBMsgRef(msg_);
				delete_flag_ = true;
			}
			else if (flag == AutoDelete) {
				delete_flag_ = true;
			}
		}
		Msg(ZQDB_MSG_TYPE type) :msg_(ZQDBMsgNew(type)), delete_flag_(true) {

		}
		Msg(const char* data, int size) : msg_(ZQDBMsgParse(data, size)), delete_flag_(true) {
			
		}
		~Msg() {
			Reset();
		}
		Msg(const Msg& msg) {
			msg_ = msg.msg_;
			delete_flag_ = msg.delete_flag_;
			if (delete_flag_) {
				ZQDBMsgRef(msg_);
			}
		}
		Msg& operator=(const Msg& msg) {
			Reset();
			msg_ = msg.msg_;
			delete_flag_ = msg.delete_flag_;
			if (delete_flag_) {
				ZQDBMsgRef(msg_);
			}
			return *this;
		}
		Msg(Msg&& msg) {
			msg_ = msg.msg_;
			msg.msg_ = nullptr;
			delete_flag_ = msg.delete_flag_;
			msg.delete_flag_ = false;
		}
		Msg& operator=(Msg&& msg) {
			Reset();
			msg_ = msg.msg_;
			msg.msg_ = nullptr;
			delete_flag_ = msg.delete_flag_;
			msg.delete_flag_ = false;
			return *this;
		}

		inline void Reset() {
			if (delete_flag_) {
				ZQDBMsgDelete(msg_);
				msg_ = nullptr;
				delete_flag_ = false;
			}
		}

		inline operator ZQDB_MSG*() const { return msg_; }
		inline ZQDB_MSG_TYPE GetMsgType() const { return msg_->msg; }

		inline const char* Serialize(size_t* size = nullptr) { return ZQDBMsgSerialize(msg_, size); }

		inline int Clear(size_t flags) { return ZQDBMsgClear(msg_, flags); }

		inline HZQDB GetNode() const { return ZQDBMsgGetNode(msg_); }
		inline int SetNode(HZQDB h) { return ZQDBMsgSetNode(msg_, h); }

		inline uint32_t GetBizType() const { return ZQDBMsgGetType(msg_); }
		inline void SetBizType(uint32_t type) { ZQDBMsgSetType(msg_, type); }
		inline uint32_t GetID() const { return ZQDBMsgGetID(msg_); }
		inline int SetID(uint32_t id) { return ZQDBMsgSetID(msg_, id); }
		inline int SetReqID(uint32_t req_type) {
			SetBizType(req_type);
			return SetID(ZQDBReqID());
		}
		inline uint32_t GetReqID() const { return GetID(); }
		inline uint32_t GetReqType() const { return GetBizType(); }

		inline const char* GetParam(const char* name) const { return ZQDBMsgGetParam(msg_, name); }
		inline const char* GetParam(const char* name, const char* def) const {
			const char* val = ZQDBMsgGetParam(msg_, name);
			if (val) {
				return val;
			}
			return def;
		}
		inline ssize_t GetParamAsInt(const char* name, ssize_t def = 0) const { return ZQDBMsgGetParamAsInt(msg_, name, def); }
		inline size_t GetParamAsUInt(const char* name, size_t def = 0) const { return ZQDBMsgGetParamAsUInt(msg_, name, def); }
		inline double GetParamAsDouble(const char* name, double def = 0) const { return ZQDBMsgGetParamAsDouble(msg_, name, def); }
		inline int SetParam(const char* name, const char* value) { return ZQDBMsgSetParam(msg_, name, value); }
		inline int SetParamAsInt(const char* name, ssize_t value) { return ZQDBMsgSetParamAsInt(msg_, name, value); }
		inline int SetParamAsUInt(const char* name, size_t value) { return ZQDBMsgSetParamAsUInt(msg_, name, value); }
		inline int SetParamAsDouble(const char* name, double value) { return ZQDBMsgSetParamAsDouble(msg_, name, value); }

		inline const char* IsContinue() const {
			if (GetParam(STR_ZQDB_MSG_PARAM_ERROR_CODE)) {
				return nullptr;
			}
			else {
				return GetParam(STR_ZQDB_MSG_PARAM_ERROR_MESSAGE);
			}
		}
		inline void SetContinue(size_t percent) {
			SetParamAsUInt(STR_ZQDB_MSG_PARAM_ERROR_MESSAGE, percent);
		}
		inline void SetContinue(const char* msg) {
			SetParam(STR_ZQDB_MSG_PARAM_ERROR_MESSAGE, msg);
		}
		inline ssize_t IsError() const { return GetParamAsInt(STR_ZQDB_MSG_PARAM_ERROR_CODE, ZQDB_MSG_PARAM_ERROR_CODE_NOERROR); }
		inline ssize_t GetErrorCode() const { return GetParamAsInt(STR_ZQDB_MSG_PARAM_ERROR_CODE, ZQDB_MSG_PARAM_ERROR_CODE_NOERROR); }
		inline const char* GetErrorMsg() const { return GetParam(STR_ZQDB_MSG_PARAM_ERROR_MESSAGE, ""); }
		inline int SetError(ssize_t code, const char* msg = nullptr) {
			if (msg) {
				SetParam(STR_ZQDB_MSG_PARAM_ERROR_MESSAGE, msg);
			}
			return SetParamAsInt(STR_ZQDB_MSG_PARAM_ERROR_CODE, code);
		}

		/*inline const char* GetAttr(size_t* size) const { return ZQDBMsgGetAttr(msg_, size); }
		inline int SetAttr(const char* data, const size_t size) { return ZQDBMsgSetAttr(msg_, data, size);  }*/

		inline const char* GetData(size_t* size) const { return ZQDBMsgGetData(msg_, size); }
		inline int SetData(const char* data, const size_t size) { return ZQDBMsgSetData(msg_, data, size); }
		inline int AppendData(const char* data, const size_t size) { return ZQDBMsgAppendData(msg_, data, size); }
	};

	template<class T>
	class NotifyMap
	{
	public:
		void OnNotifyStatus(HZQDB h) { }
		void OnNotifyAdd(HZQDB h) { }
		void OnNotifyRemove(HZQDB h) { }
		void OnNotifyUpdate(HZQDB h) { }
		void OnNotify(HZQDB h, ZQDB_NOTIFY_TYPE notify) {
			T* pT = static_cast<T*>(this);
			switch (notify)
			{
			case ZQDB_NOTIFY_STATUS: {
				pT->OnNotifyStatus(h);
			} break;
			case ZQDB_NOTIFY_ADD: {
				pT->OnNotifyAdd(h);
			} break;
			case ZQDB_NOTIFY_REMOVE: {
				pT->OnNotifyRemove(h);
			} break;
			case ZQDB_NOTIFY_UPDATE: {
				pT->OnNotifyUpdate(h);
			} break;
			}
		}
	};

	template<class T>
	class NotifyImplT : public NotifyMap<T>
	{
		typedef NotifyMap<T> Base;
	public:
		using Base::Base;

		void HandleNotify(HZQDB h, ZQDB_NOTIFY_TYPE notify)
		{
			T* pT = static_cast<T*>(this);
			pT->OnNotify(h, notify);
		}
	};

	template<class T>
	class NotifyImplExT : public NotifyImplT<T>
	{
		typedef NotifyImplT<T> Base;
	protected:
		std::map<HZQDB, std::function<void(HZQDB, ZQDB_NOTIFY_TYPE)>> notify_cbs_;
		std::shared_mutex notify_mt_;
	public:
		using Base::Base;

		bool IsRegisterNotify(HZQDB h)
		{
			std::shared_lock<std::shared_mutex> lock(notify_mt_);
			return notify_cbs_.find(h) != notify_cbs_.end();
		}

		void RegisterNotify(HZQDB h, std::function<void(HZQDB, ZQDB_NOTIFY_TYPE)>&& cb)
		{
			std::unique_lock<std::shared_mutex> lock(notify_mt_);
			notify_cbs_[h] = std::move(cb);
		}

		void UnRegisterNotify(HZQDB h) {
			std::unique_lock<std::shared_mutex> lock(notify_mt_);
			notify_cbs_.erase(h);
		}

		void UnRegisterNotifyAll()
		{
			std::unique_lock<std::shared_mutex> lock(notify_mt_);
			notify_cbs_.clear();
		}

		void HandleNotify(HZQDB h, ZQDB_NOTIFY_TYPE notify)
		{
			T* pT = static_cast<T*>(this);
			pT->OnNotify(h, notify);
			{
				std::shared_lock<std::shared_mutex> lock(notify_mt_);
				auto it = notify_cbs_.find(h);
				if (it != notify_cbs_.end()) {
					const auto& cb = it->second;
					//lock.unlock();
					cb(h, notify);
				}
			}
		}
	};
}

#endif//

#endif//_H_ZQDBASE_H_